package org.study.atomikos.mybatis.boot.config;

import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.*;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

/**
 * Primary 数据源的 MyBatis 配置。说明与注意：
 * 1、配置类上使用 @MapperScan 注解来指定当前数据源下定义的 Entity 和 Mapper 的包路径；另外需要指定 sqlSessionFactory 和 sqlSessionTemplate，这两个具体实现在该配置类中类中初始化。
 * 2、配置类的构造函数中，通过 @Qualifier 注解来指定具体要用哪个数据源，其名字对应在 DataSourceConfiguration 配置类中的数据源定义的函数名。
 * 3、配置类中定义 SqlSessionFactory 和 SqlSessionTemplate 的实现，注意具体使用的数据源正确。
 *
 * @author Administrator
 * @date 2021-11-29
 */
@Configuration
@EnableConfigurationProperties
@MapperScan(basePackages = "org.study.atomikos.mybatis.boot.mapper.primary",
        // 由于这里同时指定了sqlSessionFactoryRef和sqlSessionTemplateRef，所以日志会打印如下警告：
        // Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.
        // 去掉sqlSessionFactoryRef的配置即可
        /*sqlSessionFactoryRef = "primarySqlSessionFactory",*/
        sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryConfig {
    @Primary
    @Bean(name = "primaryDataSource")
    @DependsOn(value = {"transactionManager"})
    @ConfigurationProperties(prefix = "spring.atomikos.datasource.primary")
    public DataSource primaryDataSource() {
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        return atomikosDataSourceBean;
    }

    @Primary
    @Bean(name = "primaryJdbcTemplate")
    public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(primaryDataSource);
        return jdbcTemplate;
    }

    @Primary
    @Bean("primarySqlSessionFactory")
    public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource primaryDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(primaryDataSource);
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        // 在控制台打印SQL语句
        configuration.setLogImpl(StdOutImpl.class);
        bean.setConfiguration(configuration);
        // bean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mappers/primary/*.xml"));
        return bean.getObject();
    }

    @Primary
    @Bean(name = "primarySqlSessionTemplate")
    public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory primarySqlSessionFactory) {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(primarySqlSessionFactory);
        return sqlSessionTemplate;
    }
}